#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include "RingQueue.hpp"
#include "Thread.hpp"
#include "Task.hpp"
using namespace std;
using ThreadModule::Thread;

//using RingQueue_t = RingQueue<int>;
//using RingQueue_t = RingQueue<task_t>;
using RingQueue_t = RingQueue<task_t>;
using fun_t = function<void(RingQueue_t &, string)>;

// 生产者对应线程
void Productor(RingQueue_t &rq, string name)
{
    // 生产
    //int n = 10;
    while (true)
    {
        //1.获取任务
        task_t t = Download;
        //2.生产任务
        rq.push(t);
        // rq.push(n); // 生产满后，生产者会阻塞到room_sem 传递的参数为引用
        cout << "Productor product data: " << "[" << name << "]" << endl;
        // cout << "sem: " << rq.GetAllSem() << endl;
    }
    // while (true)
    // {
    //     printf("Productor:[%s]\n", name.c_str());
    //     sleep(1);
    // }
}
// 消费者对应线程
void Consumer(RingQueue_t &rq, string name)
{
    // 消费
    //int n;
    while (true)
    {
        sleep(1);
        //1.获取任务
        task_t t;
        rq.pop(t);
        //2.执行任务
        t();
        cout << "[" << name << "]" << endl;
        // rq.pop(n); // 消费空后，消费者会阻塞到data_sem
        // cout << "Consumer consume data: " << n << "[" << name << "]" << endl;
        // cout << "sem: " << rq.GetAllSem() << endl;
    }
    // while (true)
    // {
    //     printf("Consumer:[%s]\n", name.c_str());
    //     sleep(1);
    // }
}

void InittComm(vector<Thread<RingQueue_t>> &t, int num, fun_t fun, RingQueue_t &rq)
{
    for (int i = 0; i < num; i++)
    {
        string name = "thread-" + to_string(i + 1);
        t.emplace_back(fun, rq, name);
        // t.back().Start();     //这样会有线程安全的问题
    }
}
void InitProductor(vector<Thread<RingQueue_t>> &t, int num, RingQueue_t &rq)
{
    InittComm(t, num, Productor, rq);
}

void InitConsumer(vector<Thread<RingQueue_t>> &t, int num, RingQueue_t &rq)
{
    InittComm(t, num, Consumer, rq);
}

void StartAllThread(vector<Thread<RingQueue_t>> &t)
{
    for (auto &thread : t)
    {
        // 线程初始化和启动需要分开
        thread.Start();
    }
}
void WaitAllThread(vector<Thread<RingQueue_t>> &t)
{
    for (auto &thread : t)
    {
        thread.Join();
    }
}
int main()
{
    RingQueue_t *rq = new RingQueue_t(5);
    vector<Thread<RingQueue_t>> threads;
    // 初始化生产者线程
    InitProductor(threads, 2, *rq);
    // 初始化消费者线程
    InitConsumer(threads, 2, *rq);
    // 启动所有线程
    StartAllThread(threads);
    // 等待所有线程
    WaitAllThread(threads);
    return 0;
}